#include <iostream>
#include "myhttp_coon.h"
#include "mylock.h"
#include "threadpool.h"
#include <arpa/inet.h>
using namespace std;

/*
   setnonblocking – 设置句柄为非阻塞方式
   */
int setnonblocking(int sockfd)
{
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
    {
        return -1;
    }
    return 0;
}

int main(){

    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in myaddr,clientaddr;
    bzero((void*)&myaddr,sizeof(myaddr));
    myaddr.sin_family=AF_INET;
    myaddr.sin_port=htons(9999);
    myaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    if(bind(sockfd,(const struct sockaddr*)&myaddr,sizeof(myaddr))<0)
    {
        perror("bind error");
    }
    if(listen(sockfd,8)<0)
    {
        perror("listen error");
    }

    int ep = epoll_create(1000);
    assert(ep != -1);
    
    struct epoll_event ev,events[1000];
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = sockfd;
        
    setnonblocking(sockfd);

    if(epoll_ctl(ep,EPOLL_CTL_ADD,sockfd,&ev) < 0)
    {
        printf("add listen socket failure\n");
        return -3;
    }

    int curfds = 1;
    int conn;
    while(1)
    {
        int ret = epoll_wait(ep,events,curfds,-1);

        if(ret < 0)
        {
            printf("epoll failure\n");
            break;
        }   
        // else if(ret == 0)
        // {
        //     printf("epoll get time out\n");
        //     continue;
        // }

        for(int i=0;i<ret;i++)
        {
            //error或者中断
            // if(events[i].events&EPOLLERR || events[i].events&EPOLLHUP)
            // {
            //     printf("epoll_wait get error in %d\n",events[i].data.fd);
            //     epoll_ctl(ep,EPOLL_CTL_DEL,events[i].data.fd,NULL);
            //     close(events[i].data.fd);
            // }
            
            if(events[i].data.fd == sockfd)//有新的客户端连接进来
            {
                socklen_t len = sizeof(clientaddr);
                bzero((void *)&clientaddr,sizeof(clientaddr));

                if(conn = accept(sockfd,(sockaddr*)&clientaddr,&len) < 0)
                {   
                   perror("accept");
                   continue;
                }

                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = conn;
                
                setnonblocking(conn);

                if(epoll_ctl(ep,EPOLL_CTL_ADD,conn,&ev) < 0)
                {
                    printf("ep add new client socket failure\n");
                    //close(events[i].data.fd);
                    continue;   
                }
                printf("epoll add new client socket[%d]\n",conn);  
                curfds++;
            }
            else //已经连接的socket此刻有数据可读
            {
                http_coon *hc=new http_coon();
                hc->init(ep,events[i].data.fd);
                hc->myread();
                hc->doit();
                hc->mywrite();
                hc->close_coon();
                curfds--;
            }
        }
    }
    close(sockfd);
}